<template>
    <div style="padding-right: -10px">
        <el-row
            :gutter="15"
            style="height: 75vh; margin-right: 0"
        >
            <el-col
                :span="6"
                class="left_box"
            >
                <el-card
                    class="box-card"
                    shadow="hover"
                >
                    <el-scrollbar style="height: 75vh; padding: 0 6px;">
                        <div class="title-box">
                            表单
                            <el-divider content-position="left" />
                        </div>
                        <el-button
                            v-for="item in Constants.defaultControlSettings"
                            :key="item.type"
                            :ref="item.type + '1'"
                            plain
                            :style="{width: item.width}"
                            class="form-item"
                            @click="clickHandler"
                            @mousedown="mousemoveHandle(item, $event)"
                        >
                            {{ item.label }}
                        </el-button>
                    </el-scrollbar>
                </el-card>
            </el-col>
            <el-col
                :span="12"
                class="center_box"
            >
                <el-card
                    class="box-card"
                    shadow="hover"
                >
                    <template #header>
                        <div class="card-header">
                            <span>设计区域</span>
                            <el-button
                                class="button"
                                type="text"
                                @click="generate"
                            >
                                根据json生成
                            </el-button>
                            <span>
                                <el-button
                                    class="button"
                                    type="text"
                                    @click="preview"
                                >
                                    效果预览
                                </el-button>
                                &nbsp;
                                <el-button
                                    class="button"
                                    type="text"
                                    @click="codePreview"
                                >
                                    代码预览
                                </el-button>
                            </span>
                        </div>
                    </template>
                    <el-scrollbar
                        ref="structure"
                        style="height: 70vh; padding: 0 8px;"
                    >
                        <form-structure
                            :json="json"
                            :form-settings-data="formSettingData"
                            @form-change="formChange"
                        />
                    </el-scrollbar>
                </el-card>
            </el-col>
            <el-col
                :span="6"
                class="right_box"
            >
                <el-card
                    class="box-card"
                    shadow="hover"
                >
                    <template #header>
                        <div class="card-header">
                            <span>设置区域</span>
                        </div>
                    </template>
                    <el-scrollbar style="height: 70vh; padding: 0 8px;">
                        <el-tabs
                            v-model="activeName"
                        >
                            <el-tab-pane
                                label="控件设置"
                                name="formControls"
                            >
                                <form-controls-settings />
                            </el-tab-pane>
                            <el-tab-pane
                                label="表单设置"
                                name="formSettings"
                            >
                                <form-settings />
                            </el-tab-pane>
                        </el-tabs>
                    </el-scrollbar>
                </el-card>
            </el-col>
        </el-row>
        <el-form
            ref="form"
            :model="tempFormModel"
            label-width="82px"
            style="z-index: 12"
        >
            <form-item
                v-for="item in controlSettings"
                v-show="currentType === item.type"
                :key="item.type"
                :ref="item.type"
                :base-form-data="tempFormModel"
                :item="item"
                :style="{position: 'fixed', width: '36.3vw', cursor: (inBlock ? 'move !important' : 'not-allowed !important')}"
                style="z-index: 12"
            />
        </el-form>
        <el-dialog
            v-model="dialogVisible1"
            title="效果预览"
            destroy-on-close
            append-to-body
            width="70%"
        >
            <trends-form
                :form-data="formData"
                :form-controls="json"
                :form-settings-data="formSettingData"
            />
        </el-dialog>
        <el-dialog
            v-model="dialogVisible2"
            title="代码预览"
            append-to-body
            width="70%"
        >
            <div class="code-content">
                <md-editor
                    v-if="dialogVisible2"
                    v-model="previewCode"
                    preview-only
                    :style="{width: '100%', height: '100%'}"
                />
            </div>
        </el-dialog>
        <el-dialog
            v-model="dialogVisible3"
            title="根据json生成"
            append-to-body
            width="50%"
        >
            <div class="code-content">
                <el-input
                    v-model="tempJson"
                    type="textarea"
                    :autosize="{ minRows: 15, maxRows: 20}"
                    placeholder="请输入json"
                />
            </div>
        </el-dialog>
    </div>
</template>

<script>
import {mapState} from "vuex";
import FormItem from "./FormItem";
import MdEditor from 'md-editor-v3';
import FormStructure from "./FormStructure";
import Constants from "../../utils/Constants";
import FormSettings from "./FormSettings";
import FormControlsSettings from "./FormControlsSettings";

export default {
    name: "FormDesigner",
    components: {FormSettings, FormControlsSettings, FormStructure, FormItem, MdEditor},
    data() {
        return {
            json: [],
            Constants,
            formData: {},
            tempJson: '',
            inBlock: false,
            formSetting: {},
            previewCode: '',
            currentType: null,
            tempFormModel: {
                Input: '',
                Textarea: '',
                Select: '',
                SelectV2: '',
                Slider: 0,
                Switch: true,
                InputNumber: 0,
                Radio: '',
                Checkbox: [],
                Password: ''
            },
            dialogVisible1: false,
            dialogVisible2: false,
            dialogVisible3: false,
            controlSettings: null,
            activeName: 'formControls'
        }
    },
    computed: {
        ...mapState({
            // 左侧菜单宽度
            currentIndex: state => state.currentIndex,
            // 表单设置
            formSettingData: state => state.formSettingData,
        })
    },
    watch: {
        tempJson() {
            try {
                this.json = JSON.parse(this.tempJson);
                this.tempJson = JSON.stringify(this.json, null, 2);
                // eslint-disable-next-line no-empty
            } catch (e) {

            }
        }
    },
    mounted() {
        this.formSetting = JSON.parse(JSON.stringify(this.formSettingData));
        this.controlSettings = JSON.parse(JSON.stringify(Constants.defaultControlSettings));
    },
    beforeUnmount() {
        document.onmousemove = null;
        document.onmouseup = null;
    },
    methods: {
        codePreview() {
            this.dialogVisible2 = true;
            /* eslint-disable */
            this.previewCode =
                `<template>
    <trends-form
    :form-data="formData"
    :form-controls="formControls"
    :form-settings-data="formSettingData"
    />
</template>

<script>
export default {
    name: 'Form',
    data() {
        return {
            formData: ${JSON.stringify(this.formData)},
            formControls: ${JSON.stringify(this.json)},
            formSettingData: ${JSON.stringify(this.formSettingData)}
        }
    }
}
<\/script>`;
            /* eslint-enable */
            // ${this.formData}
            // ${this.json}
            this.previewCode = `\`\`\`vue\n${this.previewCode}\n\`\`\``
        },
        clickHandler(evt) {
            let target = evt.target;
            if(target.nodeName === "SPAN"){
                target = evt.target.parentNode;
            }
            target.blur();
            this.$nextTick(() => this.$nextTick(() => this.currentType = null))
        },
        // 根据json生成
        generate() {
            this.dialogVisible3 = true;
        },
        // 弹框
        preview() {
            this.dialogVisible1 = true;
        },
        formChange(formData) {
            this.formData = formData;
        },
        mousemoveHandle(item, event) {
            if (event.button !== 0) {
                return;
            }
            let that = this;
            // 光标移动事件
            document.onmousemove = function (e) {
                that.currentType = item.type;
                // 获取设计区域的坐标信息
                let clientRect = that.$refs['structure'].$el.getBoundingClientRect();
                // 判断光标是否在设计区域
                if (e.clientX < clientRect.left || e.clientY < clientRect.top
                    || e.clientX > (clientRect.left + clientRect.width)
                    || e.clientY > (clientRect.top + clientRect.height)) {
                    // 不在设计区域
                    that.inBlock = false;
                    // 移除设计区域中预览的控件
                    that.json = that.json.filter(e => !e.prev);
                    that.currentType = item.type;
                } else {
                    that.inBlock = true;
                    if (that.json.filter(e => e.prev).length === 0) {
                        let control = JSON.parse(JSON.stringify(Constants.defaultControlSettings[item.type]));
                        control.prev = true;
                        control.id = new Date().getTime();
                        control.name = control.name + new Date().getTime();
                        // 添加控件
                        that.json.push(control);
                    }
                    that.currentType = null;
                }
                // 拖动的控件跟着鼠标移动
                that.$refs[item.type].$el.style.left = (e.clientX - 50) + 'px';
                that.$refs[item.type].$el.style.top = (e.clientY - 20) + 'px';
            };
            // 光标松开事件
            document.onmouseup = function(){
                // 移除预览的控件
                // that.json = that.json.filter(e => !e.prev);
                let previews = that.json.filter(e => e.prev);
                if (previews.length === 1) {
                    if (that.inBlock) {
                        let data = previews[0];
                        data.prev = false;
                    } else {
                        that.currentType = null;
                    }
                }
                // 初始化
                that.$refs[item.type + '1'].$el.blur();
                that.currentType = null;
                document.onmousemove = null;
                document.onmouseup = null;
            };
        }
    }
}
</script>

<style scoped>
    .box-card {
        height: 75vh;
        padding-bottom: 30px;
    }
    .el-button+::v-deep(.el-button) {
        margin-left: 0;
    }
    .title-box {
    }
    .form-item {
        border-radius: 0;
        cursor: move;
        margin: 0 10px 12px 0;
    }
    ::v-deep(.el-card__body) {
        padding: 10px;
    }
    .card-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .button {
        padding: 0;
        min-height: 0;
    }
    .code-content {
        white-space: pre-wrap;
    }
</style>
